{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Updating a Historical Marquee Portfolio\n",
    "\n",
    "If you already have a portfolio in Marquee, the GS Quant SDK provides a simple and intuitive workflow to update positions and rerun reports.\n",
    "\n",
    "You will need to be an admin on the portfolio you would like to update. If you are not an admin, please ask a portfolio admin to [edit the portfolio's entitlements](../examples/marquee/01_edit_portfolio_entitlements.ipynb) to include you."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 1: Authenticate and Initialize Your Session\n",
    "\n",
    "First you will import the necessary modules and add your client id and client secret."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "import datetime as dt\n",
    "\n",
    "from gs_quant.markets.portfolio_manager import PortfolioManager\n",
    "from gs_quant.session import GsSession, Environment\n",
    "from gs_quant.markets.position_set import PositionSet\n",
    "\n",
    "client = None\n",
    "secret = None\n",
    "scopes = None\n",
    "\n",
    "## External users must fill in their client ID and secret below and comment out the line below\n",
    "\n",
    "# client = 'ENTER CLIENT ID'\n",
    "# secret = 'ENTER CLIENT SECRET'\n",
    "\n",
    "GsSession.use(\n",
    "    Environment.PROD,\n",
    "    client_id=client,\n",
    "    client_secret=secret,\n",
    ")\n",
    "\n",
    "print('GS Session initialized.')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 2: Define Your Portfolio ID and the Positions You Would Like to Upload\n",
    "\n",
    "Portfolio positions in Marquee are stored on a holding basis, when means you only upload positions for days where you are rebalancing your portfolio. \n",
    "\n",
    "Positions can be uploaded using the following identifiers:\n",
    "\n",
    "| Identifier                        | Descriptions                                                              |\n",
    "|-----------------------------------|---------------------------------------------------------------------------|\n",
    "| BLOOMBERG ID = \"BBID\"             | Bloomberg identifier and exchange code (GS UN)                            |\n",
    "| SEDOL = \"SEDOL\"                   | LSE Stock Exchange Daily Official List code (2407966)                     |\n",
    "| CUSIP = \"CUSIP\"                   | Committee on Uniform Security Identification Procedures code (38141G104)  |\n",
    "| ISIN = \"ISIN\"                     | International Securities Identification Number (US38141G1040)             |\n",
    "| GSID = \"GSID\"                     | Goldman Sachs Identifier                                                  |\n",
    "| REUTERS ID = \"RIC\"                | Thompson Reuters Instrument Code (RIC), (GS.N)                            |\n",
    "| TICKER = \"TICKER\"                 | Exchange ticker (GS)                                                      |\n",
    "\n",
    " Depending on your quantity type, you can upload by shares, weights, or exposures.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "portfolio_id = 'PORTFOLIO ID'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "### Uploading Positions Using Shares\n",
    "Portfolio quantity type uses share counts."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "portfolio_position_sets = [\n",
    "    PositionSet.from_dicts(\n",
    "        date=dt.date(day=3, month=5, year=2021),\n",
    "        positions=[{'identifier': 'AAPL UW', 'quantity': 25}, {'identifier': 'GS UN', 'quantity': 50}],\n",
    "    ),\n",
    "    PositionSet.from_dicts(\n",
    "        date=dt.date(day=1, month=7, year=2021),\n",
    "        positions=[{'identifier': 'AAPL UW', 'quantity': 25}, {'identifier': 'GS UN', 'quantity': 50}],\n",
    "    ),\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "### Uploading Positions Using Exposures\n",
    "Portfolio quantity type uses notional values."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "portfolio_position_sets = [\n",
    "    PositionSet.from_dicts(\n",
    "        date=dt.date(day=3, month=5, year=2021),\n",
    "        positions=[{'identifier': 'AAPL UW', 'notional': 2500}, {'identifier': 'GS UN', 'notional': 5000}],\n",
    "    ),\n",
    "    PositionSet.from_dicts(\n",
    "        date=dt.date(day=1, month=7, year=2021),\n",
    "        positions=[{'identifier': 'AAPL UW', 'notional': 2500}, {'identifier': 'GS UN', 'notional': 500}],\n",
    "    ),\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "### Uploading Positions Using Weights\n",
    "Portfolio quantity type uses weight values."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "portfolio_position_sets = [\n",
    "    PositionSet.from_dicts(\n",
    "        date=dt.date(day=3, month=5, year=2021),\n",
    "        reference_notional=10000,\n",
    "        positions=[{'identifier': 'AAPL UW', 'weight': 0.5}, {'identifier': 'GS UN', 'weight': 0.5}],\n",
    "    ),\n",
    "    PositionSet.from_dicts(\n",
    "        date=dt.date(day=1, month=7, year=2021),\n",
    "        reference_notional=10000,\n",
    "        positions=[{'identifier': 'AAPL UW', 'weight': 0.5}, {'identifier': 'GS UN', 'weight': 0.5}],\n",
    "    ),\n",
    "]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "### Resolve Positions"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "for pos_set in portfolio_position_sets:\n",
    "    pos_set.resolve()\n",
    "    if len(pos_set.unresolved_positions) > 0:\n",
    "        print(\n",
    "            f'The following positions on {pos_set.date} could not be resolved: {[p.identifier for p in pos_set.unresolved_positions]}'\n",
    "        )\n",
    "    else:\n",
    "        print(f\"All positions on {pos_set.date} have been resolved and saved.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## Price Positions (Weights & Exposures)\n",
    "When uploading positions by weights or exposures they must priced and converted to share quantities before being uploaded to the portfolio.\n",
    "Select the currency you want to price your positions with. If you do not specify, default is USD."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "currency = 'USD'\n",
    "\n",
    "for pos_set in portfolio_position_sets:\n",
    "    pos_set.price(currency)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": false
   },
   "source": [
    "## Step 3: Post Positions to the Marquee Portfolio"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "pm = PortfolioManager(portfolio_id)\n",
    "pm.update_positions(portfolio_position_sets)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Have your positions as a dataframe?\n",
    "\n",
    "If you have a day's positions in a dataframe with columns `identifer` (string values), `quantity` (float values),\n",
    "and optionally `tags` (dictionary values), you can turn them into a `PositionSet` object by using the\n",
    "`PositionSet.from_frame()` function:\n",
    "\n",
    "`position_set = PositionSet.from_frame(positions_df, datetime_date)`\n",
    "\n",
    "You can also substitute the `quantity` column with either `notional` (float values) or `weight` (float values) columns."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "# positions_df = DATAFRAME WITH POSITIONS\n",
    "# datetime_date = POSITIONS' DATE\n",
    "\n",
    "portfolio_position_sets = []\n",
    "portfolio_position_sets.append(PositionSet.from_frame(positions_df, datetime_date))\n",
    "\n",
    "for pos_set in portfolio_position_sets:\n",
    "    pos_set.resolve()\n",
    "    if len(pos_set.unresolved_positions) > 0:\n",
    "        print(\n",
    "            f'The following positions on {pos_set.date} could not be resolved: {[p.identifier for p in pos_set.unresolved_positions]}'\n",
    "        )\n",
    "    else:\n",
    "        print(f\"All positions on {pos_set.date} have been resolved and saved.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Step 4: Reschedule All Portfolio Reports\n",
    "\n",
    "Now that the portfolio has new positions, it's time to rerun all reports associated with the portfolio so your performance, risk, and other analytics reflect these new positions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "pycharm": {
     "name": "#%%\n"
    }
   },
   "outputs": [],
   "source": [
    "pm.schedule_reports()\n",
    "\n",
    "print('All portfolio reports scheduled.')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "*Other questions? Reach out to the [Portfolio Analytics team](mailto:gs-marquee-analytics-support@gs.com)!*"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.13"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
